home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / CmeBSB.c < prev    next >
C/C++ Source or Header  |  2001-06-24  |  24KB  |  811 lines

  1. /* (from) $XConsortium: SmeBSB.c,v 1.16 91/03/15 15:59:41 gildea Exp $ */
  2.  
  3. /*
  4.  * Modifications Copyright 1995, 1999, 2000 by Paul Mattes.
  5.  *  Permission to use, copy, modify, and distribute this software and its
  6.  *  documentation for any purpose and without fee is hereby granted,
  7.  *  provided that the above copyright notice appear in all copies and that
  8.  *  both that copyright notice and this permission notice appear in
  9.  *  supporting documentation.
  10.  *
  11.  * Copyright 1989 Massachusetts Institute of Technology
  12.  *
  13.  * Permission to use, copy, modify, distribute, and sell this software and its
  14.  * documentation for any purpose is hereby granted without fee, provided that
  15.  * the above copyright notice appear in all copies and that both that
  16.  * copyright notice and this permission notice appear in supporting
  17.  * documentation, and that the name of M.I.T. not be used in advertising or
  18.  * publicity pertaining to distribution of the software without specific,
  19.  * written prior permission.  M.I.T. makes no representations about the
  20.  * suitability of this software for any purpose.  It is provided "as is"
  21.  * without express or implied warranty.
  22.  *
  23.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  25.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  26.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  27.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  28.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  29.  */
  30.  
  31. /*
  32.  * CmeBSB.c - Source code file for BSB Menu Entry object.
  33.  * (from) SmeBSB.c - Source code file for BSB Menu Entry object.
  34.  *
  35.  * Date:    September 26, 1989
  36.  *
  37.  * By:      Chris D. Peterson
  38.  *          MIT X Consortium 
  39.  *          kit@expo.lcs.mit.edu
  40.  */
  41.  
  42. #include "globals.h"
  43. #if defined(X3270_MENUS) /*[*/
  44.  
  45. #include <X11/IntrinsicP.h>
  46. #include <X11/StringDefs.h>
  47. #include <X11/Xos.h>
  48.  
  49. #include <X11/Xmu/Drawing.h>
  50.  
  51. #include <X11/Xaw/XawInit.h>
  52. #include "CmplxMenu.h"
  53. #include "CmeBSBP.h"
  54. #include <X11/Xaw/Cardinals.h>
  55. #include <X11/Xaw/MenuButton.h>
  56.  
  57. #include <stdio.h>
  58.  
  59. #define ONE_HUNDRED 100
  60.  
  61. #define offset(field) XtOffsetOf(CmeBSBRec, cme_bsb.field)
  62.  
  63. static XtResource resources[] = {
  64.   {XtNlabel,  XtCLabel, XtRString, sizeof(String),
  65.      offset(label), XtRString, NULL},
  66.   {XtNvertSpace,  XtCVertSpace, XtRInt, sizeof(int),
  67.      offset(vert_space), XtRImmediate, (XtPointer) 25},
  68.   {XtNleftBitmap, XtCLeftBitmap, XtRBitmap, sizeof(Pixmap),
  69.      offset(left_bitmap), XtRImmediate, (XtPointer)None},
  70.   {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify),
  71.      offset(justify), XtRImmediate, (XtPointer) XtJustifyLeft},
  72.   {XtNmenuName, XtCMenuName, XtRString, sizeof(String),
  73.      offset(menu_name), XtRString, NULL},
  74.   {XtNrightBitmap, XtCRightBitmap, XtRBitmap, sizeof(Pixmap),
  75.      offset(right_bitmap), XtRImmediate, (XtPointer)None},
  76.   {XtNleftMargin,  XtCHorizontalMargins, XtRDimension, sizeof(Dimension),
  77.      offset(left_margin), XtRImmediate, (XtPointer) 4},
  78.   {XtNrightMargin,  XtCHorizontalMargins, XtRDimension, sizeof(Dimension),
  79.      offset(right_margin), XtRImmediate, (XtPointer) 4},
  80.   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  81.      offset(foreground), XtRString, XtDefaultForeground},
  82.   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  83.      offset(font), XtRString, XtDefaultFont},
  84. };   
  85. #undef offset
  86.  
  87. /*
  88.  * Semi Public function definitions. 
  89.  */
  90.  
  91. static void FlipColors(Widget);
  92. static void Initialize(Widget, Widget);
  93. static void Destroy(Widget);
  94. static void Redisplay(Widget, XEvent *, Region);
  95. static void FlipOn(Widget);
  96. static void FlipOff(Widget);
  97. static void PopupMenu(Widget);
  98. static void ClassInitialize(void);
  99. static Boolean SetValues(Widget, Widget, Widget);
  100. static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
  101.     XtWidgetGeometry *);
  102.  
  103. /* 
  104.  * Private Function Definitions.
  105.  */
  106.  
  107. static void GetDefaultSize(Widget, Dimension *, Dimension *);
  108. static void DrawBitmaps(Widget, GC);
  109. static void GetBitmapInfo(Widget, Boolean);
  110. static void CreateGCs(Widget);
  111. static void DestroyGCs(Widget);
  112.     
  113. #define def_superclass (&cmeClassRec)
  114. CmeBSBClassRec cmeBSBClassRec = {
  115.   {
  116.     /* superclass         */    (WidgetClass) 0,
  117.     /* class_name         */    "CmeBSB",
  118.     /* size               */    sizeof(CmeBSBRec),
  119.     /* class_initializer  */    ClassInitialize,
  120.     /* class_part_initialize*/    NULL,
  121.     /* Class init'ed      */    FALSE,
  122.     /* initialize         */    (XtInitProc)Initialize,
  123.     /* initialize_hook    */    NULL,
  124.     /* realize            */    NULL,
  125.     /* actions            */    NULL,
  126.     /* num_actions        */    ZERO,
  127.     /* resources          */    resources,
  128.     /* resource_count     */    XtNumber(resources),
  129.     /* xrm_class          */    NULLQUARK,
  130.     /* compress_motion    */    FALSE, 
  131.     /* compress_exposure  */    FALSE,
  132.     /* compress_enterleave*/     FALSE,
  133.     /* visible_interest   */    FALSE,
  134.     /* destroy            */    Destroy,
  135.     /* resize             */    NULL,
  136.     /* expose             */    Redisplay,
  137.     /* set_values         */    (XtSetValuesFunc)SetValues,
  138.     /* set_values_hook    */    NULL,
  139.     /* set_values_almost  */    0,  
  140.     /* get_values_hook    */    NULL,            
  141.     /* accept_focus       */    NULL,
  142.     /* intrinsics version */    XtVersion,
  143.     /* callback offsets   */    NULL,
  144.     /* tm_table          */    NULL,
  145.     /* query_geometry      */    QueryGeometry,
  146.     /* display_accelerator*/    NULL,
  147.     /* extension      */    NULL
  148.   },{
  149.     /* Menu Entry Fields */
  150.       
  151.     /* highlight */             FlipOn,
  152.     /* unhighlight */           FlipOff,
  153. #ifndef AMIGA
  154.     /* notify */        XtInheritNotify,
  155. #else
  156.     /* notify */         NULL,
  157. #endif
  158.     /* extension      */    NULL
  159.   }, {
  160.     /* BSB Menu entry Fields */  
  161.  
  162.     /* extension      */    NULL
  163.   }
  164. };
  165.  
  166. WidgetClass cmeBSBObjectClass = (WidgetClass) &cmeBSBClassRec;
  167.  
  168. #ifdef AMIGA
  169. void AMIGA_INIT_CMEBSB(void)
  170.  {
  171.  cmeBSBClassRec.superclass=def_superclass;
  172.  cmeBSBClassRec.set_values_almost=XtInheritSetValuesAlmost;
  173.  cmeBSBClassRec.notify=def_superclass->notify;
  174.  
  175.  }
  176. #endif
  177.  
  178. /************************************************************
  179.  *
  180.  * Semi-Public Functions.
  181.  *
  182.  ************************************************************/
  183.  
  184. /*    Function Name: ClassInitialize
  185.  *    Description: Initializes the CmeBSBObject. 
  186.  *    Arguments: none.
  187.  *    Returns: none.
  188.  */
  189.  
  190. void relay_func2(
  191.     XrmValue*        a/* args */,
  192.     Cardinal*        b/* num_args */,
  193.     XrmValuePtr        c/* fromVal */,
  194.     XrmValuePtr        d/* toVal */
  195. )
  196. {
  197. XmuCvtStringToJustify(a,b,c,d);
  198. }
  199.  
  200. static void 
  201. ClassInitialize(void)
  202. {
  203.     XawInitializeWidgetSet();
  204.     XtAddConverter( XtRString, XtRJustify, relay_func2, NULL, 0 );
  205. }
  206.  
  207. /*      Function Name: Initialize
  208.  *      Description: Initializes the complex menu widget
  209.  *      Arguments: request - the widget requested by the argument list.
  210.  *                 new     - the new widget with both resource and non
  211.  *                           resource values.
  212.  *      Returns: none.
  213.  */
  214.  
  215. static void
  216. Initialize(Widget request unused, Widget new)
  217. {
  218.     CmeBSBObject entry = (CmeBSBObject) new;
  219.  
  220.     if (entry->cme_bsb.label == NULL) 
  221.     entry->cme_bsb.label = XtName(new);
  222.     else
  223.     entry->cme_bsb.label = XtNewString( entry->cme_bsb.label );
  224.  
  225.     GetDefaultSize(new, &(entry->rectangle.width), &(entry->rectangle.height));
  226.     CreateGCs(new);
  227.  
  228.     entry->cme_bsb.left_bitmap_width = entry->cme_bsb.left_bitmap_height = 0;
  229.     entry->cme_bsb.right_bitmap_width = entry->cme_bsb.right_bitmap_height = 0;
  230.  
  231.     GetBitmapInfo(new, TRUE);    /* Left Bitmap Info */
  232.     GetBitmapInfo(new, FALSE);    /* Right Bitmap Info */
  233.  
  234.     entry->cme_bsb.ticking = False;
  235. }
  236.  
  237. /*      Function Name: Destroy
  238.  *      Description: Called at destroy time, cleans up.
  239.  *      Arguments: w - the complex menu widget.
  240.  *      Returns: none.
  241.  */
  242.  
  243. static void
  244. Destroy(Widget w)
  245. {
  246.     CmeBSBObject entry = (CmeBSBObject) w;
  247.  
  248.     DestroyGCs(w);
  249.     if (entry->cme_bsb.label != XtName(w))
  250.     XtFree(entry->cme_bsb.label);
  251.     if (entry->cme_bsb.ticking)
  252.     XtRemoveTimeOut(entry->cme_bsb.id);
  253. }
  254.  
  255. /*      Function Name: Redisplay
  256.  *      Description: Redisplays the contents of the widget.
  257.  *      Arguments: w - the complex menu widget.
  258.  *                 event - the X event that caused this redisplay.
  259.  *                 region - the region the needs to be repainted. 
  260.  *      Returns: none.
  261.  */
  262.  
  263. static void
  264. Redisplay(Widget w, XEvent *event unused, Region region unused)
  265. {
  266.     GC gc;
  267.     CmeBSBObject entry = (CmeBSBObject) w;
  268.     int    font_ascent, font_descent, y_loc;
  269.  
  270.     entry->cme_bsb.set_values_area_cleared = FALSE;    
  271.     font_ascent = entry->cme_bsb.font->max_bounds.ascent;
  272.     font_descent = entry->cme_bsb.font->max_bounds.descent;
  273.  
  274.     y_loc = entry->rectangle.y;
  275.     
  276.     if (XtIsSensitive(w) && XtIsSensitive( XtParent(w) ) ) {
  277.     if ( w == XawComplexMenuGetActiveEntry(XtParent(w)) ) {
  278.         XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), 
  279.                entry->cme_bsb.norm_gc, 0, y_loc,
  280.                (unsigned int) entry->rectangle.width,
  281.                (unsigned int) entry->rectangle.height);
  282.         gc = entry->cme_bsb.rev_gc;
  283.     }
  284.     else
  285.         gc = entry->cme_bsb.norm_gc;
  286.     }
  287.     else
  288.     gc = entry->cme_bsb.norm_gray_gc;
  289.     
  290.     if (entry->cme_bsb.label != NULL) {
  291.     int x_loc = entry->cme_bsb.left_margin;
  292.     int len = strlen(entry->cme_bsb.label);
  293.     char * label = entry->cme_bsb.label;
  294.  
  295.     switch(entry->cme_bsb.justify) {
  296.         int width, t_width;
  297.  
  298.     case XtJustifyCenter:
  299.         t_width = XTextWidth(entry->cme_bsb.font, label, len);
  300.         width = entry->rectangle.width - (entry->cme_bsb.left_margin +
  301.                           entry->cme_bsb.right_margin);
  302.         x_loc += (width - t_width)/2;
  303.         break;
  304.     case XtJustifyRight:
  305.         t_width = XTextWidth(entry->cme_bsb.font, label, len);
  306.         x_loc = entry->rectangle.width - (entry->cme_bsb.right_margin +
  307.                           t_width);
  308.         break;
  309.     case XtJustifyLeft:
  310.     default:
  311.         break;
  312.     }
  313.  
  314.     y_loc += ((int)entry->rectangle.height - 
  315.           (font_ascent + font_descent)) / 2 + font_ascent;
  316.     
  317.     XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc,
  318.             x_loc, y_loc, label, len);
  319.     }
  320.  
  321.     DrawBitmaps(w, gc);
  322. }
  323.  
  324.  
  325. /*      Function Name: SetValues
  326.  *      Description: Relayout the menu when one of the resources is changed.
  327.  *      Arguments: current - current state of the widget.
  328.  *                 request - what was requested.
  329.  *                 new - what the widget will become.
  330.  *      Returns: none
  331.  */
  332.  
  333. static Boolean
  334. SetValues(Widget current, Widget request unused, Widget new)
  335. {
  336.     CmeBSBObject entry = (CmeBSBObject) new;
  337.     CmeBSBObject old_entry = (CmeBSBObject) current;
  338.     Boolean ret_val = FALSE;
  339.  
  340.     if (old_entry->cme_bsb.label != entry->cme_bsb.label) {
  341.         if (old_entry->cme_bsb.label != XtName( new ) )
  342.         XtFree( (char *) old_entry->cme_bsb.label );
  343.  
  344.     if (entry->cme_bsb.label != XtName(new) ) 
  345.         entry->cme_bsb.label = XtNewString( entry->cme_bsb.label );
  346.  
  347.     ret_val = True;
  348.     }
  349.  
  350.     if (entry->rectangle.sensitive != old_entry->rectangle.sensitive )
  351.     ret_val = TRUE;
  352.  
  353.     if (entry->cme_bsb.left_bitmap != old_entry->cme_bsb.left_bitmap) {
  354.     GetBitmapInfo(new, TRUE);
  355.     ret_val = TRUE;
  356.     }
  357.  
  358.     if (entry->cme_bsb.right_bitmap != old_entry->cme_bsb.right_bitmap) {
  359.     GetBitmapInfo(new, FALSE);
  360.     ret_val = TRUE;
  361.     }
  362.  
  363.     if ( (old_entry->cme_bsb.font != entry->cme_bsb.font) ||
  364.      (old_entry->cme_bsb.foreground != entry->cme_bsb.foreground) ) {
  365.     DestroyGCs(current);
  366.     CreateGCs(new);
  367.     ret_val = TRUE;
  368.     }
  369.  
  370.     if (ret_val) {
  371.     GetDefaultSize(new, 
  372.                &(entry->rectangle.width), &(entry->rectangle.height));
  373.     entry->cme_bsb.set_values_area_cleared = TRUE;
  374.     }
  375.     return(ret_val);
  376. }
  377.  
  378. /*    Function Name: QueryGeometry.
  379.  *    Description: Returns the preferred geometry for this widget.
  380.  *    Arguments: w - the menu entry object.
  381.  *                 itended, return_val - the intended and return geometry info.
  382.  *    Returns: A Geometry Result.
  383.  *
  384.  * See the Intrinsics manual for details on what this function is for.
  385.  * 
  386.  * I just return the height and width of the label plus the margins.
  387.  */
  388.  
  389. static XtGeometryResult
  390. QueryGeometry(Widget w, XtWidgetGeometry *intended,
  391.     XtWidgetGeometry *return_val)
  392. {
  393.     CmeBSBObject entry = (CmeBSBObject) w;
  394.     Dimension width, height;
  395.     XtGeometryResult ret_val = XtGeometryYes;
  396.     XtGeometryMask mode = intended->request_mode;
  397.  
  398.     GetDefaultSize(w, &width, &height );    
  399.  
  400.     if ( ((mode & CWWidth) && (intended->width != width)) ||
  401.      !(mode & CWWidth) ) {
  402.     return_val->request_mode |= CWWidth;
  403.     return_val->width = width;
  404.     ret_val = XtGeometryAlmost;
  405.     }
  406.  
  407.     if ( ((mode & CWHeight) && (intended->height != height)) ||
  408.      !(mode & CWHeight) ) {
  409.     return_val->request_mode |= CWHeight;
  410.     return_val->height = height;
  411.     ret_val = XtGeometryAlmost;
  412.     }
  413.  
  414.     if (ret_val == XtGeometryAlmost) {
  415.     mode = return_val->request_mode;
  416.     
  417.     if ( ((mode & CWWidth) && (width == entry->rectangle.width)) &&
  418.          ((mode & CWHeight) && (height == entry->rectangle.height)) )
  419.         return(XtGeometryNo);
  420.     }
  421.  
  422.     return(ret_val);
  423. }
  424.  
  425. /*      Function Name: OnCallback
  426.  *      Description: Timeout callback for submenu pop-up.
  427.  *      Arguments: closure - the bsb menu entry widget.
  428.  *      Returns: none.
  429.  */
  430.  
  431. static void
  432. OnCallback(XtPointer closure, XtIntervalId *id unused)
  433. {
  434.     Widget w = (Widget) closure;
  435.     CmeBSBObject entry = (CmeBSBObject) w;
  436.  
  437.     if (entry->cme_bsb.ticking &&
  438.         XawComplexMenuGetActiveEntry(XtParent(w)) == w)
  439.     PopupMenu(w);
  440.     entry->cme_bsb.ticking = False;
  441. }
  442.  
  443. /*      Function Name: FlipOn
  444.  *      Description: Invert the colors of the current entry.
  445.  *      Arguments: w - the bsb menu entry widget.
  446.  *      Returns: none.
  447.  */
  448.  
  449. static void 
  450. FlipOn(Widget w)
  451. {
  452.     CmeBSBObject entry = (CmeBSBObject) w;
  453.  
  454.     FlipColors(w);
  455.     if (entry->cme_bsb.menu_name == NULL)
  456.     return;
  457.     if (entry->cme_bsb.ticking)
  458.     XtRemoveTimeOut(entry->cme_bsb.id);
  459.     entry->cme_bsb.ticking = True;
  460.     entry->cme_bsb.id = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
  461.         200L, OnCallback, (XtPointer)w);
  462. }
  463.  
  464. /*      Function Name: FlipOff
  465.  *      Description: Invert the colors of the current entry.
  466.  *      Arguments: w - the bsb menu entry widget.
  467.  *      Returns: none.
  468.  */
  469.  
  470. static void 
  471. FlipOff(Widget w)
  472. {
  473.     CmeBSBObject entry = (CmeBSBObject) w;
  474.     Widget menu = NULL, temp;
  475.  
  476.     FlipColors(w);
  477.     if (entry->cme_bsb.menu_name == NULL)
  478.     return;
  479.     if (entry->cme_bsb.ticking) {
  480.     XtRemoveTimeOut(entry->cme_bsb.id);
  481.     entry->cme_bsb.ticking = False;
  482.     return;
  483.     }
  484.  
  485.     temp = w;
  486.     while(temp != NULL) {
  487.     menu = XtNameToWidget(temp, entry->cme_bsb.menu_name);
  488.     if (menu == NULL) 
  489.         temp = XtParent(temp);
  490.     else
  491.         break;
  492.     }
  493.  
  494.     if (menu == NULL) {
  495.     char error_buf[BUFSIZ];
  496.     (void) sprintf(error_buf, "CmeBSB: %s %s.",
  497.         "Could not find menu widget named", entry->cme_bsb.menu_name);
  498.     XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
  499.     return;
  500.     }
  501.     XtPopdown(menu);
  502. }
  503.     
  504. /*      Function Name: FlipColors
  505.  *      Description: Invert the colors of the current entry.
  506.  *      Arguments: w - the bsb menu entry widget.
  507.  *      Returns: none.
  508.  */
  509.  
  510. static void 
  511. FlipColors(Widget w)
  512. {
  513.     CmeBSBObject entry = (CmeBSBObject) w;
  514.  
  515.     if (entry->cme_bsb.set_values_area_cleared) return;
  516.  
  517.     XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
  518.            entry->cme_bsb.invert_gc, 0, (int) entry->rectangle.y,
  519.            (unsigned int) entry->rectangle.width, 
  520.            (unsigned int) entry->rectangle.height);
  521. }
  522.  
  523. /************************************************************
  524.  *
  525.  * Private Functions.
  526.  *
  527.  ************************************************************/
  528.  
  529. /*    Function Name: GetDefaultSize
  530.  *    Description: Calculates the Default (preferred) size of
  531.  *                   this menu entry.
  532.  *    Arguments: w - the menu entry widget.
  533.  *                 width, height - default sizes (RETURNED).
  534.  *    Returns: none.
  535.  */
  536.  
  537. static void
  538. GetDefaultSize(Widget w, Dimension *width, Dimension *height)
  539. {
  540.     CmeBSBObject entry = (CmeBSBObject) w;
  541.  
  542.     if (entry->cme_bsb.label == NULL) 
  543.     *width = 0;
  544.     else
  545.     *width = XTextWidth(entry->cme_bsb.font, entry->cme_bsb.label,
  546.                 strlen(entry->cme_bsb.label));
  547.  
  548.     *width += entry->cme_bsb.left_margin + entry->cme_bsb.right_margin;
  549.     
  550.     *height = (entry->cme_bsb.font->max_bounds.ascent +
  551.            entry->cme_bsb.font->max_bounds.descent);
  552.  
  553.     *height = ((int)*height * ( ONE_HUNDRED + 
  554.                     entry->cme_bsb.vert_space )) / ONE_HUNDRED;
  555. }
  556.  
  557. /*      Function Name: DrawBitmaps
  558.  *      Description: Draws left and right bitmaps.
  559.  *      Arguments: w - the complex menu widget.
  560.  *                 gc - graphics context to use for drawing.
  561.  *      Returns: none
  562.  */
  563.  
  564. static void
  565. DrawBitmaps(Widget w, GC gc)
  566. {
  567.     int x_loc, y_loc;
  568.     CmeBSBObject entry = (CmeBSBObject) w;
  569.     
  570.     if ( (entry->cme_bsb.left_bitmap == None) && 
  571.      (entry->cme_bsb.right_bitmap == None) ) return;
  572.  
  573. /*
  574.  * Draw Left Bitmap.
  575.  */
  576.  
  577.   if (entry->cme_bsb.left_bitmap != None) {
  578.     x_loc = (int)(entry->cme_bsb.left_margin -
  579.               entry->cme_bsb.left_bitmap_width) / 2;
  580.  
  581.     y_loc = entry->rectangle.y + (int)(entry->rectangle.height -
  582.                        entry->cme_bsb.left_bitmap_height) / 2;
  583.  
  584.     XCopyPlane(XtDisplayOfObject(w), entry->cme_bsb.left_bitmap,
  585.            XtWindowOfObject(w), gc, 0, 0, 
  586.            entry->cme_bsb.left_bitmap_width,
  587.            entry->cme_bsb.left_bitmap_height, x_loc, y_loc, 1);
  588.   }
  589.  
  590. /*
  591.  * Draw Right Bitmap.
  592.  */
  593.  
  594.  
  595.   if (entry->cme_bsb.right_bitmap != None) {
  596.     x_loc = entry->rectangle.width -
  597.           (int)(entry->cme_bsb.right_margin +
  598.             entry->cme_bsb.right_bitmap_width) / 2;
  599.  
  600.     y_loc = entry->rectangle.y + (int)(entry->rectangle.height -
  601.                        entry->cme_bsb.right_bitmap_height) / 2;
  602.  
  603.     XCopyPlane(XtDisplayOfObject(w), entry->cme_bsb.right_bitmap,
  604.            XtWindowOfObject(w), gc, 0, 0, 
  605.            entry->cme_bsb.right_bitmap_width,
  606.            entry->cme_bsb.right_bitmap_height, x_loc, y_loc, 1);
  607.   }
  608. }
  609.  
  610. /*      Function Name: GetBitmapInfo
  611.  *      Description: Gets the bitmap information from either of the bitmaps.
  612.  *      Arguments: w - the bsb menu entry widget.
  613.  *                 is_left - TRUE if we are testing left bitmap,
  614.  *                           FALSE if we are testing the right bitmap.
  615.  *      Returns: none
  616.  */
  617.  
  618. static void
  619. GetBitmapInfo(Widget w, Boolean is_left)
  620. {
  621.     CmeBSBObject entry = (CmeBSBObject) w;    
  622.     unsigned int depth, bw;
  623.     Window root;
  624.     int x, y;
  625.     unsigned int width, height;
  626.     char buf[BUFSIZ];
  627.     
  628.     if (is_left) {
  629.     if (entry->cme_bsb.left_bitmap != None) {
  630.         if (!XGetGeometry(XtDisplayOfObject(w), 
  631.                   entry->cme_bsb.left_bitmap, &root, 
  632.                   &x, &y, &width, &height, &bw, &depth)) {
  633.         (void) sprintf(buf, "CmeBSB Object: %s %s \"%s\".", "Could not",
  634.             "get Left Bitmap geometry information for menu entry ",
  635.             XtName(w));
  636.         XtAppError(XtWidgetToApplicationContext(w), buf);
  637.         }
  638.         if (depth != 1) {
  639.         (void) sprintf(buf, "CmeBSB Object: %s \"%s\"%s.", 
  640.             "Left Bitmap of entry ", 
  641.             XtName(w), " is not one bit deep.");
  642.         XtAppError(XtWidgetToApplicationContext(w), buf);
  643.         }
  644.         entry->cme_bsb.left_bitmap_width = (Dimension) width; 
  645.         entry->cme_bsb.left_bitmap_height = (Dimension) height;
  646.     }
  647.     }
  648.     else if (entry->cme_bsb.right_bitmap != None) {
  649.     if (!XGetGeometry(XtDisplayOfObject(w),
  650.               entry->cme_bsb.right_bitmap, &root,
  651.               &x, &y, &width, &height, &bw, &depth)) {
  652.         (void) sprintf(buf, "CmeBSB Object: %s %s \"%s\".", "Could not",
  653.             "get Right Bitmap geometry information for menu entry ",
  654.             XtName(w));
  655.         XtAppError(XtWidgetToApplicationContext(w), buf);
  656.     }
  657.     if (depth != 1) {
  658.         (void) sprintf(buf, "CmeBSB Object: %s \"%s\"%s.", 
  659.             "Right Bitmap of entry ", XtName(w),
  660.             " is not one bit deep.");
  661.         XtAppError(XtWidgetToApplicationContext(w), buf);
  662.     }
  663.     entry->cme_bsb.right_bitmap_width = (Dimension) width; 
  664.     entry->cme_bsb.right_bitmap_height = (Dimension) height;
  665.     }
  666. }      
  667.  
  668. /*      Function Name: CreateGCs
  669.  *      Description: Creates all gc's for the complex menu widget.
  670.  *      Arguments: w - the complex menu widget.
  671.  *      Returns: none.
  672.  */
  673.  
  674. static void
  675. CreateGCs(Widget w)
  676. {
  677.     CmeBSBObject entry = (CmeBSBObject) w;    
  678.     XGCValues values;
  679.     XtGCMask mask;
  680.     
  681.     values.foreground = XtParent(w)->core.background_pixel;
  682.     values.background = entry->cme_bsb.foreground;
  683.     values.font = entry->cme_bsb.font->fid;
  684.     values.graphics_exposures = FALSE;
  685.     mask        = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
  686.     entry->cme_bsb.rev_gc = XtGetGC(w, mask, &values);
  687.     
  688.     values.foreground = entry->cme_bsb.foreground;
  689.     values.background = XtParent(w)->core.background_pixel;
  690.     entry->cme_bsb.norm_gc = XtGetGC(w, mask, &values);
  691.     
  692.     values.fill_style = FillTiled;
  693.     values.tile   = XmuCreateStippledPixmap(XtScreenOfObject(w), 
  694.                         entry->cme_bsb.foreground,
  695.                         XtParent(w)->core.background_pixel,
  696.                         XtParent(w)->core.depth);
  697.     values.graphics_exposures = FALSE;
  698.     mask |= GCTile | GCFillStyle;
  699.     entry->cme_bsb.norm_gray_gc = XtGetGC(w, mask, &values);
  700.     
  701.     values.foreground ^= values.background;
  702.     values.background = 0;
  703.     values.function = GXxor;
  704.     mask = GCForeground | GCBackground | GCGraphicsExposures | GCFunction;
  705.     entry->cme_bsb.invert_gc = XtGetGC(w, mask, &values);
  706. }
  707.  
  708. /*      Function Name: DestroyGCs
  709.  *      Description: Removes all gc's for the complex menu widget.
  710.  *      Arguments: w - the complex menu widget.
  711.  *      Returns: none.
  712.  */
  713.  
  714. static void
  715. DestroyGCs(Widget w)
  716. {
  717.     CmeBSBObject entry = (CmeBSBObject) w;    
  718.  
  719.     XtReleaseGC(w, entry->cme_bsb.norm_gc);
  720.     XtReleaseGC(w, entry->cme_bsb.norm_gray_gc);
  721.     XtReleaseGC(w, entry->cme_bsb.rev_gc);
  722.     XtReleaseGC(w, entry->cme_bsb.invert_gc);
  723. }
  724.  
  725. /*      Function Name: PopupMenu
  726.  *      Description: Pops up the pullright menu associated with this widget.
  727.  *      Arguments: w - the complex menu widget.
  728.  *      Returns: none.
  729.  */
  730.  
  731. static void
  732. PopupMenu(Widget w)
  733. {
  734.     CmeBSBObject entry = (CmeBSBObject) w;
  735.     Widget menu = NULL, temp;
  736.     Arg arglist[3];
  737.     Cardinal num_args;
  738.     int menu_x, menu_y, menu_width, menu_height, button_width;
  739.     Position button_x, button_y;
  740.  
  741.     temp = w;
  742.     while(temp != NULL) {
  743.     menu = XtNameToWidget(temp, entry->cme_bsb.menu_name);
  744.     if (menu == NULL) 
  745.         temp = XtParent(temp);
  746.     else
  747.         break;
  748.     }
  749.  
  750.     if (menu == NULL) {
  751.     char error_buf[BUFSIZ];
  752.     (void) sprintf(error_buf, "CmeBSB: %s %s.",
  753.         "Could not find menu widget named", entry->cme_bsb.menu_name);
  754.     XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
  755.     return;
  756.     }
  757.     if (!XtIsRealized(menu))
  758.     XtRealizeWidget(menu);
  759.  
  760.     menu_width = menu->core.width + 2 * menu->core.border_width;
  761.     button_width = w->core.width + 2 * w->core.border_width;
  762.     menu_height = menu->core.height + 2 * menu->core.border_width;
  763.  
  764.     XtTranslateCoords(w, 0, 0, &button_x, &button_y);
  765.     menu_x = button_x + button_width + menu->core.border_width - 10; /* XXX */
  766.     menu_y = button_y + 1;
  767.  
  768.     if (menu_x >= 0) {
  769.     int scr_width = WidthOfScreen(XtScreen(menu));
  770.     if (menu_x + menu_width > scr_width)
  771.         menu_x = scr_width - menu_width;
  772.     }
  773.     if (menu_x < 0) 
  774.     menu_x = 0;
  775.  
  776.     if (menu_y >= 0) {
  777.     int scr_height = HeightOfScreen(XtScreen(menu));
  778.     if (menu_y + menu_height > scr_height)
  779.         menu_y = scr_height - menu_height;
  780.     }
  781.     if (menu_y < 0)
  782.     menu_y = 0;
  783.  
  784.     num_args = 0;
  785.     XtSetArg(arglist[num_args], XtNx, menu_x); num_args++;
  786.     XtSetArg(arglist[num_args], XtNy, menu_y); num_args++;
  787.     XtSetArg(arglist[num_args], XtNcMparent, XtParent(w)); num_args++;
  788.     XtSetValues(menu, arglist, num_args);
  789.  
  790.     XtPopup(menu, XtGrabNonexclusive);
  791. }
  792.  
  793. #ifdef apollo
  794.  
  795. /*
  796.  * The apollo compiler that we have optimizes out my code for
  797.  * FlipColors() since it is static. and no one executes it in this
  798.  * file.  I am setting the function pointer into the class structure so
  799.  * that it can be called by my parent who will tell me to when to
  800.  * highlight and unhighlight.
  801.  */
  802.  
  803. void
  804. _XawCmeBSBApolloHack(void)
  805. {
  806.     FlipColors();
  807. }
  808. #endif /* apollo */
  809.  
  810. #endif /*]*/
  811.